<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
    <meta charset="UTF-8">
    <title></title>
    <link rel="stylesheet" href="../../../../bower_components/animate.css/animate.css"/>
</head>
<body ng-controller="Ctrl as c">
<ul>
    <li ng-repeat="item in c.items track by $index" class="xxx animated">
        {{item.name}}
        <button ng-click="c.moveToTop($index)">置顶</button>
        <button ng-click="c.remove($index)">删除</button>
    </li>
</ul>
<input type="text" ng-model="c.todo.name"/>
<button ng-click="c.addTodo()">添加</button>
<script src="../../../../../../../bower_components/angular/angular.js"></script>
<script src="../../../../../../../bower_components/angular-animate/angular-animate.js"></script>
<script>
    var app = angular.module('app', [
        'ngAnimate'
    ]);
    // decorator(name, decorator) 装饰器 可以改变已经存在的 service 的实现
    // 在config中实现
    //    app.config(['$provide', function ($provide) {
    //        $provide.decorator('$log', ['$delegate', function ($delegate) {
    //            var methods = ['log', 'info'];
    //            angular.forEach(methods, function (o) {
    //                $delegate[o] = decoratorLogger($delegate[o]);
    //            });
    //
    //            function decoratorLogger(fn) {
    //
    //                return function () {
    //                    var args = Array.prototype.slice.call(arguments);
    //                    args.unshift(new Date().toISOString() + ' =>');
    //                    fn.apply(null, args);
    //                }
    //            }
    //
    //            $delegate.custom = function () {
    //                console.log(arguments);
    //            };
    //            return $delegate;
    //        }]);
    //    }]);
    // 直接使用 app.decorator 实现
    app.decorator('$log', function ($delegate) { // $delegate 即 $log 对象
        var methods = ['log', 'info']; // 改变$log的 log info 方法
        angular.forEach(methods, function (o) {
            $delegate[o] = decoratorLogger($delegate[o]);
        });

        function decoratorLogger(fn) {

            return function () {
                var args = Array.prototype.slice.call(arguments);
                args.unshift(new Date().toISOString() + ' =>'); // 添加输出时的时间
                fn.apply(null, args);
            }
        }

        $delegate.custom = function () { // 拓展一个 custom 方法
            console.log(arguments);
        };
        return $delegate;
    });

    // animation(name, animationFactory) 使用 animation 需要引入 ngAnimate 模块
    app.animation('.xxx', ['$animate',function ($animate) { // 动画的名字以点（.）开头

        var classs = 'bounceIn bounceOut bounceInUp';
        return {
            // el: jQlite对象或jQuery对象(引入了jQuery时); done: 一个动画结束时的回调函数。指令对应的行为动作被暂停，直到回调函数被调用。
            enter: function (el, done) {
                console.log('enter');
                el.removeClass(classs)
                        .addClass('bounceIn')
                        .one('animationend', function () {
                            done();// 动画完成后再执行dom删除操作
                        });
            },
            leave: function (el, done) {
                console.log('leave');
                el.removeClass(classs)
                        .addClass('bounceOut')
                        .one('animationend', function () {
                            done();
                        });
            },
            move: function (el, done) {
                console.log('move');
                el.removeClass(classs).
                        addClass('bounceInUp')
                        .one('animationend', function () {
                            done();
                        });
            }
        };
    }]);

    app.controller('Ctrl', ['$log', function ($log) {

        $log.log(1, 'asda', {a: '1', b: 'b'});
        $log.custom('a', 2, 'c');

        var vm = this;
        vm.items = [
            {name: 'underscore源码'}
        ];
        vm.addTodo = function () {
            vm.items.push(vm.todo);
            vm.todo = {};
        };
        vm.remove = function (index) {
            vm.items.splice(index, 1);
        };
        vm.moveToTop = function (index) {
            vm.items.unshift(vm.items.splice(index, 1)[0]);
        };
    }]);
</script>
</body>
</html>